<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>木结构试验室安全测试</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/animate.css/4.0.0/animate.min.css" rel="stylesheet" type="text/css">
    <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
    <style>
        nav .brand-logo {
            font-size: 1.3rem;
            padding: auto 0;
        }
        .card .card-content .card-title {
            margin-bottom: 20px;
        }
        .card .card-content .content-btn {
            margin: 20px 0;
        }
        .allquestions-body {
            margin: 10px 0 0;
            font-size: 1.2rem;
        }
        ul.allquestions-choices {
            margin-top: 4px;
        }

        ul.allquestions-choices > li {
            padding-left: 1.5rem;
            font-size: 1.1rem;
            list-style-type: circle;
            list-style-position: inside;
        }
        .name-table td {
            padding-top: 4px;
            padding-bottom: 4px;
        }
        .answer-selections {
            padding-bottom: 20px;
        }
        .answer-selections label {
            color: #555;
        }

    </style>
</head>



<body>
    <div id="vue-app" style="display:none;" v-show="isMounted">
    <nav>
        <div class="nav-wrapper teal">
            <a href="#" class="brand-logo center">木结构试验室安全测试</a>
            <ul class="left">
                <li><a href="javascript:void(0);" @click="navBtnEvent"><i class="material-icons">{{navBtnIcon}}</i></a></li>
            </ul>
        </div>
    </nav>    
    <div class="progress teal lighten-4" style="margin-top:0;height: 3px;" :style="{visibility: progressVisible}">
        <div class="teal darken-4" :class="{determinate:progress, indeterminate:!progress}" :style="{width: progress+'%'}"></div>
    </div>
    <div class="container">
        <div class="row">
            <div class="col s12 m2 l3"></div>
            <div class="col s12 m8 l6">
                <div class="wrapper" style="height: 80vh;">
                        <!-- page-welcome -->
                        <div class="card" v-if="status===0">
                            <div class="card-content">
                                <div class="card-title"><span>输入信息</span></div>
                                <form>
                                        <div class="input-field">
                                            <input id="student-id" type="text" class="validate"  v-model="studentId">
                                            <label for="student-id" :class="{active:studentId}">学号</label>
                                        </div>
                                        <div class="input-field">
                                            <input id="student-name" type="text" class="validate" v-model="studentName">
                                            <label for="student-name" :class="{active:studentName}">姓名</label>
                                        </div>
                                        <div class="content-btn">
                                            <button class="waves-effect waves-light btn"  :class="{disabled: !studentReady||!questions}" @click="status=7;">开始答题</button>
                                        </div>
                                </form>
                            </div>
                            <div class="card-action">
                                <a href="javascript:void(0);" @click="status=6;">查看题库</a>
                                <a href="javascript:void(0);" @click="status=5;">考试通过名单</a>
                            </div>
                        </div>
                        <!-- page-notice -->
                        <div class="card" v-if="status===7">
                            <div class="card-content">
                                <div class="card-title"><span>答题须知</span></div>
                                <div>
                                    <ol>
                                        <li>题型为单选题和多选题两种；</li>
                                        <li>如果答错，请根据显示的正确答案重新作答；</li>
                                        <li>答题过程中请不要退出答题页面，否则重新开始；</li>
                                        <li>答题不限时间。</li>
                                    </ol>
                                </div>
                                <button class="waves-effect waves-light btn" @click="startQuestions">我已知晓</button>
                            </div>
                        </div>
                        <!-- page-passed -->
                        <div class="card" v-if="status===5">
                            <div class="card-content">
                                <div class="card-title"><span>考试通过名单</span></div>
                                <div class="striped name-table">
                                    <table>
                                        <thead><tr><th>学号</th><th>姓名</th></tr></thead>
                                        <tbody>
                                            <tr v-for="student in nameList">
                                                <td>{{student.attributes.id}}</td>
                                                <td>{{student.attributes.name}}</td>
                                            </tr>
                                        </tbody>
                                    </table>
                                </div>
                            </div>
                        </div>
                        <!-- page-allquestions -->
                        <div class="card" style="height: 100%;" v-if="status===6">
                            <div class="card-content">
                                <div class="card-title"><span>题库</span></div>
                                <div><span>注：标注绿色的为正确答案</span></div>
                                <div v-for="(question, i) in questions">
                                    <div class="allquestions-body">{{i+1}}. {{question.attributes.body}} 
                                        <span v-if="question.attributes.multiple">(单选)</span>
                                        <span v-else>(多选)</span>
                                    </div>
                                    <div>
                                        <ul class="allquestions-choices">
                                            <li v-for="(choice, j) in question.attributes.choices">
                                                <span :class="{'teal-text darken-2': correctAnswers[i][j]}">{{choice}}</span>
                                            </li>
                                        </ul>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <!-- page-answer -->
                        <div style="position:relative;height:100%;width:100%;" v-if="status===1||status===2||status===3">
                        <transition :enter-active-class="transitionEnter" :leave-active-class="transitionLeave">
                        <div class="question-wrapper" style="position:absolute;width:100%;height:100%;" :key="currentIndex">
                        <div class="card" style="height:100%;" v-show="i===currentIndex" v-for="(question, i) in questions">
                            <div class="card-image teal lighten-4" style="height: 35%;">
                                <div class="blue-grey-text lighten-2" style="position:absolute;padding:10px 24px;">{{currentType}} ({{currentIndex+1}} / {{count}})</div>
                                <span class="card-title black-text" style="font-size: large;">
                                    {{question.attributes.body}}
                                </span>
                                <a class="btn-floating halfway-fab waves-effect waves-light teal" @click="actionBtnEvent"><i class="material-icons">{{actionBtnIcon}}</i></a>
                            </div>
                            <div class="card-content" style="height: 50%;">
                                <div class="answer-selections" v-if="question.attributes.multiple">
                                    <form>
                                        <div class="form-control" v-for="(choice, j) in question.attributes.choices">
                                            <label>
                                                <input name="question" :value="j" type="checkbox" v-model="selections"/>
                                                <span :class="{'teal-text darken-2': status!==1&&correctAnswers[i][j], 'red-text': status!==1&&wrongAnswers[j]}">{{choice}}</span>
                                            </label>
                                        </div>
                                    </form>
                                </div>
                                <div class="answer-selections" v-else>
                                    <form>
                                        <div class="form-control" v-for="(choice, j) in question.attributes.choices">
                                            <label>
                                                <input name="question" :value="j" type="radio" v-model="selections"/>
                                                <span :class="{'teal-text darken-2': status!==1&&correctAnswers[i][j], 'red-text': status!==1&&wrongAnswers[j]}">{{choice}}</span>
                                            </label>
                                        </div>
                                    </form>
                                </div>
                                <div class="result-wrapper" style="height: 15%;" v-if="result">
                                    <div v-if="result.status">{{result.status}}</div>
                                    <div v-if="result.answer">{{result.answer}}</div>
                                    <div v-if="result.explain">{{result.explain}}</div>
                                </div>
                            </div>
                            <div class="card-action">
                                提示：<a href="#">参考链接</a>
                            </div>
                        </div>
                        </div>
                        </transition>
                        </div>
                        <!-- page-done -->
                        <div class="card" v-if="status===4&&progress!==0">
                            <div class="card-content">
                                <div class="center"><i class="medium material-icons">done</i></div>
                                <div class="card-title center"><span> 恭喜！考试通过。</span></div>
                            </div>
                            <div class="card-action">
                                <a href="javascript:void(0);" @click="status=5;">考试通过名单</a>
                            </div>
                        </div>
                </div>
            </div>
        </div>
    </div>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/js/materialize.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/leancloud-storage@4.6.0/dist/av-min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>

<script>
    const { Query, User } = AV;
    AV.init({
        appId:'PFiiVjMh7P4U4y4lTFNnlYhd-gzGzoHsz',
        appKey: 'XAQklXbRaaDbX9Q5MbegdwqQ',
        serverURL: 'https://pfiivjmh.lc-cn-n1-shared.com',
    })
    
    var app = new Vue({
        el: '#vue-app',
        data () { 
            return {
                questions: null,
                status: 0, // 0:outside, 1:thinking, 2:wrong, 3:right, 4:upload, 5:namelist, 6:allquestions, 7:notice.
                selections: [],
                currentIndex: 0,
                count: null,
                finish: false,
                studentId: '',
                studentName: '',
                studentExists: false,
                uploaded: false,
                isMounted: false,
                nameList: null,
                correctAnswers: [[]],
                progress: 0,
                transitionEnter: "animate__animated animate__fadeInRight animate__faster",
                transitionLeave: "animate__animated animate__fadeOutLeft animate__faster",
            }
        },
        mounted: function() {
            this.isMounted = true;
            // load data from leancloud.
            let ok = false;
            const query1 = new AV.Query('Question');
            query1.notEqualTo('weight', 0);
            query1.find().then(questions => {
                this.questions = questions.sort((a,b) => {
                    return a.attributes.weight - b.attributes.weight;
                });
                this.count = this.questions.length;
                this.correctAnswers = new Array(this.count).fill(0).map((_, i)=>{
                    return new Array(this.questions[i].attributes.choices.length).fill(false).map((_, j) => {
                        return this.questions[i].attributes.answers.indexOf(j) !== -1 ? true : false
                    })
                });
                if (ok) {
                    this.progress = -1;
                } else {
                    ok = true;
                }
            });
            const query2 = new AV.Query('Pass');
            query2.find().then(passes => {
                this.nameList = passes.reverse();
                if (ok) {
                    this.progress = -1;
                } else {
                    ok = true;
                }
            })
        },
        methods: {
            urlFor: function(str) {
                if (str.startsWith('http')) {
                    return str;
                } else {
                    return '/timbertj/'+str;
                }
            },
            startQuestions: function(){
                this.status = 1;
                this.progress = 1.0 / this.count * 100;
                this.preTreatUser();
            },
            preTreatUser: function() {
                let query = new AV.Query('Pass');
                query.equalTo('id', this.studentId);
                query.equalTo('name', this.studentName);
                query.first().then((item) => {
                    if (item) {
                        this.studentExists = true;
                    } 
                }, (error) => {
                    console.log("error feching student information.");
                    this.studentExists = false;
                });
            },
            checkAnswer: function(i) {
                // check answer
                if (this.questions[i].attributes.multiple) {
                    // check multiple choice
                    let a = this.questions[i].attributes.answers;
                    let b = this.selections;
                    let l = a.length;
                    let disagree = l;
                    if (l == b.length) {
                        for (let j = l-1; j>=0; j--) {
                            if (b.indexOf(a[j]) != -1) {
                                disagree -= 1;
                            }
                        }
                        if (!disagree) {
                            return true;
                        }
                    }
                } else {
                    // check simple choice. Note: v-model binding radio btn returns a number.
                    if (this.questions[i].attributes.answers[0] === this.selections) {
                        return true;
                    }
                }
                return false;
            },
            actionBtnEvent: function() {
                switch (this.status) {
                    case 1:
                        // submit answer
                        let correct = this.checkAnswer(this.currentIndex);
                        if (correct) {
                            this.status = 3;
                        } else {
                            this.status = 2;
                        }
                        break;
                    case 2:
                        // reanswer this question.
                        this.selections = [];
                        this.status = 1;
                        break;
                    case 3:
                        if (this.currentIndex == this.count-1) {
                            this.status = 4;
                            this.progress = 0;
                            this.currentIndex = 0;
                            this.uploadResult();
                        } else {
                            this.currentIndex += 1;
                            this.progress = (this.currentIndex+1) * 100.0 / this.count;
                        }
                        this.selections = [];
                        break;
                    case 6:
                        this.status = 0;
                        break;
                }
            },
            uploadResult: function() {
                if (this.studentExists) {
                    this.uploaded = true;
                    this.progress = -1;
                } else {
                    let Pass = AV.Object.extend('Pass');
                    let pass = new Pass();
                    pass.set('id', this.studentId);
                    pass.set('name', this.studentName);
                    pass.set('pass', true);
                    pass.save().then(() => {
                        const query = new AV.Query('Pass');
                            query.find().then(passes => {
                                this.nameList = passes.reverse();
                                this.uploaded = true;
                                this.progress = -1;
                            })
                    }, (error) => {
                        this.progress = -1;
                        alert("错误：上传失败！");
                    });
                }
            },
            navBtnEvent () {
                switch (this.status) {
                    case 0:
                        window.location.href="http://donghl.gitee.io/timbertj/";
                        break;
                    case 1:
                    case 2:
                    case 3:
                        this.transitionEnter= "animate__animated animate__fadeInLeft animate__faster";
                        this.transitionLeave= "animate__animated animate__fadeOutRight animate__faster";
                        if (this.currentIndex == 0) {
                            this.status = 0;
                            this.progress = -1;
                            setTimeout(()=>{
                                // this.status = 0;
                                this.transitionEnter= "animate__animated animate__fadeInRight animate__faster";
                                this.transitionLeave= "animate__animated animate__fadeOutLeft animate__faster";
                            }, 0);
                        } else {
                            this.currentIndex -= 1;
                            this.status = 1;
                            setTimeout(()=>{
                                // this.currentIndex -= 1;
                                this.transitionEnter= "animate__animated animate__fadeInRight animate__faster";
                                this.transitionLeave= "animate__animated animate__fadeOutLeft animate__faster";
                            }, 0);
                        }
                        break;
                    case 4:
                    case 5:
                    case 6:
                    case 7:
                        this.status = 0;
                }
            }
        },
        watch: {
            selections: function() {
                if (this.status == 2 || this.status == 3) {
                    this.status = 1;
                }
            }
        },
        computed: {
            actionBtnIcon: function() {
                switch (this.status) {
                    case 1:
                        return 'done';
                    case 2:
                        return 'cached';
                    case 3:
                        if (this.currentIndex == this.count-1) {
                            return 'done_all';
                        }
                        return 'arrow_forward';
                    default:
                        return ''
                }
            },
            studentReady: function() {
                return this.studentName && this.studentId;
            },
            result: function() {
                switch (this.status) {
                    case 0:
                    case 1:
                        return {};
                    case 2:
                        let answer = '正确答案：';
                        for (let i of this.questions[this.currentIndex].attributes.answers) {
                            answer += this.questions[this.currentIndex].attributes.choices[i] + ' ';
                        }
                        let explain = this.questions[this.currentIndex].attributes.explain
                        if (explain) {
                            explain = '解析：' + explain;
                        }
                        return {status: '回答错误', answer:answer, explain:explain};
                    case 3:
                        return {status: '回答正确！'}
                }
            },
            currentType: function() {
                if (this.questions) {
                    if (this.currentIndex < this.count) {
                        if (this.questions[this.currentIndex].attributes.multiple) {
                            return '多选题';
                        } else {
                            return '单选题';
                        }
                    } else {
                        return '';
                    }
                } else {
                    return '';
                }
            },
            wrongAnswers: function() {
                if (this.questions && this.currentIndex < this.count) {
                    let question = this.questions[this.currentIndex];
                    let sty = new Array(question.attributes.choices.length).fill(0).map((_, j) => {
                        if (this.status === 1) {
                            return false;
                        } else if (this.status === 2) {
                            if (question.attributes.multiple) {
                                return this.selections.indexOf(j) !== -1 && !this.correctAnswers[this.currentIndex][j] ? true : false;
                            } else {
                                return this.selections === j ? true : false;
                            }
                        } else {
                            return false;
                        }
                    });
                    return sty;
                } else {
                    return [[]];
                }
            },
            progressVisible : function() {
                if (this.progress === -1 || this.progress === 0 && !this.studentReady) {
                    return "hidden";
                } else {
                    return "visible";
                }
            },
            navBtnIcon : function() {
                if (this.status==0) {
                    return 'home';
                } else {
                    return 'arrow_back';
                }
            }
        }
    })
</script>
</body>
</html>